package com.kylin.common.security.handler;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSON;
import com.kylin.common.redis.service.RedisService;
import com.kylin.common.security.domain.ClaimsInfo;
import com.kylin.common.security.domain.LoginUser;
import com.kylin.common.security.exception.AuthErrorMessage;
import com.kylin.common.security.util.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义退出处理器
 * @author wuhao
 * @version 1.0 - 2023/1/13
 */
@Slf4j
@Component
public class LogoutHandlerImpl implements LogoutHandler {

    @Autowired
    private RedisService redisService;

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        LoginUser user = (LoginUser) authentication.getPrincipal();
        log.info("username: {}  is offline now", user.getUsername());
        // 自定义业务处理
        // 在JwtTokenAuthenticationFilter我们在credentials中放入了token
        String token = (String) authentication.getCredentials();
        ClaimsInfo claimsInfo;
        try {
            Claims claims = JwtUtils.parseJwt(token);
            claimsInfo = JSON.parseObject(claims.getSubject(), ClaimsInfo.class);
        }catch (ExpiredJwtException e) {
            throw new InternalAuthenticationServiceException(AuthErrorMessage.TOKEN_EXPIRED.getMessage());
        }
        catch (Exception e) {
            throw new InternalAuthenticationServiceException(AuthErrorMessage.TOKEN_ERROR.getMessage());
        }

        // 删除缓存信息即可
        redisService.deleteObject(claimsInfo.getTokenKey());
    }
}
